package com.ytjj.qmyx.mall.service.thirdpay.mhkj;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ytjj.common.constants.AlipayConstants;
import com.ytjj.common.exception.ApiException;
import com.ytjj.common.exception.GlobalExceptionHandler;
import com.ytjj.common.service.RedisService;
import com.ytjj.common.utils.DateTimeUtil;
import com.ytjj.common.utils.HttpClientUtil;
import com.ytjj.common.utils.IPUtil;
import com.ytjj.common.utils.TokenUtil;
import com.ytjj.qmyx.mall.config.SupplyApiConfig;
import com.ytjj.qmyx.mall.constants.IsPayConstant;
import com.ytjj.qmyx.mall.enums.OrderPaySource;
import com.ytjj.qmyx.mall.enums.OrderPayTypeEnums;
import com.ytjj.qmyx.mall.enums.OrderStatusEnums;
import com.ytjj.qmyx.mall.enums.PayPayTypeEnums;
import com.ytjj.qmyx.mall.mapper.*;
import com.ytjj.qmyx.mall.model.*;
import com.ytjj.qmyx.mall.model.dto.WxPayDto;
import com.ytjj.qmyx.mall.model.request.UpdateOrderStatusRequest;
import com.ytjj.qmyx.mall.service.OrdersService;
import com.ytjj.qmyx.mall.service.ProductService;
import com.ytjj.qmyx.mall.service.WxService;
import com.ytjj.qmyx.mall.service.thirdpay.entity.WysOrderNotify;
import com.ytjj.qmyx.mall.service.thirdpay.mhkj.utils.PayUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.*;

/**
 * 米花科技支付相关业务
 */
@Service("APP-MHKJ")
@Slf4j
@RefreshScope
public class MhkjService implements WxService<WxPayDto> {
    // 商户标识
    private static final String merAccount = "xxx";
    //私钥
    private static final String merKey = "xxxx";
    //公钥
    private static final String publicKey = "xxxx";

    //商户号
    private static final String merNo = "xxxx";
    //api地址
    private static final String mhkjApiUrl = "xxxx";


    @Value("${mhkjNotifyUrl:}")
    private String mhkjNotifyUrl;

    @Value("${mhkjReturnUrlNotifyUrl:}")
    private String mhkjReturnUrlNotifyUrl;

    @Resource
    private OrdersDao ordersDao;

    @Resource
    private OrdersPayMapper ordersPayMapper;
    @Resource
    private OrdersMapper ordersMapper;
    @Resource
    private OrdersInfoMapper ordersInfoMapper;

    @Resource
    private RedisService redisService;
    @Resource
    private ProductService productService;

    @Resource
    private OrdersService ordersService;

    @Resource
    private ReturnGoodsDao returnGoodsDao;
    @Resource
    private SupplyApiConfig supplyApiConfig;
    @Resource
    private AlipayConstants alipayConstants;

    @PostConstruct
    public void init() {

    }

    @Override
    public Map<String, String> doUnifiedOrder(WxPayDto wxAppPayDto) throws Exception {
        Map<String,String> param = new HashMap<>();

        String ip;
        try {
            ip = IPUtil.getIpAddress(TokenUtil.getRequest());
        } catch (Exception e) {
            log.error("ip获取报错:",e);
            ip = "0.0.0.0";
        }

        String payWay ="WEIXIN";
        String payType = "H5_WEIXIN";

        JSONObject json = new JSONObject();
        json.put("merAccount", merAccount);
        json.put("merNo", merNo);
        json.put("orderId", wxAppPayDto.getResOrderNo());
        json.put("time", System.currentTimeMillis()/1000);
        json.put("amount", wxAppPayDto.getRealTotalMoney());
        json.put("product", wxAppPayDto.getBody());
        json.put("productDesc", wxAppPayDto.getBody());
        json.put("payWay", wxAppPayDto.getWayCode());
        if ("WEIXIN".equals(wxAppPayDto.getWayCode())){
            json.put("payType", "H5_WEIXIN");
        }
        if ("ALIPAY".equals(wxAppPayDto.getWayCode())){
            json.put("payType", "ALIPAY_H5");
        }
        json.put("userIp", ip);


        Orders orders = null;
        if(StringUtils.isNotBlank(wxAppPayDto.getOrderNo())){
            orders = ordersDao.queryOrdersByOrderNo(wxAppPayDto.getOrderNo());
        }
        if (orders ==null){
            throw new ApiException("订单不存在,请重新下单或者联系在线客服!");
        }
        if(StringUtils.isNotBlank(wxAppPayDto.getSourcePlatform())){
            String returnUrl = wxAppPayDto.getSourcePlatform();
            returnUrl = returnUrl + "?sourcePlatform="+wxAppPayDto.getSourcePlatform()+"&orderNo="+orders.getOrderNo()+"&token="+orders.getH5Token();
//            json.put("returnUrl",returnUrl);
        }

        json.put("notifyUrl", mhkjNotifyUrl);
        String sign = PayUtils.buildSign(json,merKey);
        json.put("sign", sign);
        String data="";
        try {
            data = PayUtils.buildDataPrivate(json,merKey);
        } catch (Exception e) {
            log.error("加密报错:",e);
        }
        JSONObject result = PayUtils.httpPost(mhkjApiUrl, merAccount, data);
        log.info("mhkjpayResult:{}",result.toString());
        if (result!=null && "000000".equals(result.getString("code"))){
            JSONObject dataResult = (JSONObject)result.get("data");
            param.put("redirectUrl",dataResult.getString("payUrl"));
            param.put("transaction_id",dataResult.getString("mbOrderId"));
        }
        return param;
    }

    public String notifyuMhkj(HttpServletRequest request){
        try{
            String data= request.getParameter("data");
            log.info("米花支付成功回调,{}",data);
            //公钥解密
            JSONObject json= PayUtils.decryptDataPublic(data, publicKey);
            //公钥验签
            String signaa = json.getString("sign");
            json.remove("sign");
            String signbb = PayUtils.buildSign(json, publicKey);
            if(signaa.equals(signbb)) {
                updateOrderInfo(json);
                return "SUCCESS";
            } else {
                return "FAILED";
            }
        } catch (Exception e) {
           log.info("米花科技回调报错,",e);
            return "FAILED";
        }
    }

    public String notifyuMhkjRefund(HttpServletRequest request){
        try{
            String data= request.getParameter("data");
            log.info("米花退款回调,{}",data);
            //公钥解密
            JSONObject json= PayUtils.decryptDataPublic(data, publicKey);
            //公钥验签
            String signaa = json.getString("sign");
            json.remove("sign");
            String signbb = PayUtils.buildSign(json, publicKey);
            if(signaa.equals(signbb)) {
                log.info("米花科技退款回调解密后json:{}",json.toJSONString());

                String status = json.getString("refundStatus");
                String mchRefundNo = json.getString("merchantRefundNo");;

                if ("REFUND_SUCCESS".equals(status)){
                    try {
                        Thread.sleep(1500);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    //修改订单相关状态
                    updateAdminOrderInfo(mchRefundNo);
                    // 退款表状态更新
                    ordersDao.updateOrderRefundStatusByRefundNo(2,mchRefundNo,json.toString());
                }
                if ("REFUND_FAIL".equals(status)){
                    // 退款表状态更新
                    ordersDao.updateOrderRefundStatusByRefundNo(3,mchRefundNo,json.toString());
                }

                return "SUCCESS";
            } else {
                return "FAILED";
            }
        } catch (Exception e) {
            log.info("米花科技退款回调报错,",e);
            return "FAILED";
        }
    }

    public void updateAdminOrderInfo(String trade_no){
        Integer orderInfoId = ordersDao.findOrderInfoIdByRefundNo(trade_no);
        log.info("trade_no:{},orderInfoId:{}",trade_no,orderInfoId);
        if (orderInfoId!=null){
            ReturnGoods returnGoodsInfo = ordersDao.selectReturnGoodsByWaitBackAmount(orderInfoId);
            log.info("ReturnGoods:{}",JSON.toJSONString(returnGoodsInfo));
            if (returnGoodsInfo!=null){
                // 同步退货管理中的退货状态
                returnGoodsDao.returnGoodsSuccess(returnGoodsInfo.getId());
                //交易关闭原因
                String closeRemarks = getCloseRemarks(returnGoodsInfo);

                //退款成功主子订单为已关闭
                OrdersInfo ordersInfo = ordersInfoMapper.selectByPrimaryKey(returnGoodsInfo.getOrdersInfoId());
                ordersDao.updateStatusByOid(returnGoodsInfo.getOrdersInfoId(), "4", closeRemarks);
                ordersDao.updateOrderStatusById(ordersInfo.getOrderId(),"4",returnGoodsInfo.getServiceNo());

                // 原路返回页中订单详情状态改为已关闭
                ordersDao.modifiedReturnRegister(returnGoodsInfo.getOrdersInfoId());

                //更新供应链订单状态  销售端调用 （当销售端退款后，需要修改订单状态）
                UpdateOrderStatusRequest updateOrderStatusRequest = new UpdateOrderStatusRequest();
                updateOrderStatusRequest.setChildOrderNo(ordersInfo.getChildOrderNo());
                updateOrderStatusRequest.setShopId(supplyApiConfig.getShopId());
                updateOrderStatusRequest.setOrderStatus(4);
                String json = JSON.toJSONString(updateOrderStatusRequest);
                HttpClientUtil.doPostJson(supplyApiConfig.getUrl() + "/order/updateOrderStatus", json, supplyApiConfig.getHeadsMap());

                //更新供应链售后信息
                YxReturnGoods yxReturnGoodsRequest = new YxReturnGoods();
                yxReturnGoodsRequest.setServiceNo(returnGoodsInfo.getServiceNo());
                yxReturnGoodsRequest.setStatus(9);

                yxReturnGoodsRequest.setShopId(supplyApiConfig.getShopId());
                String json2 = JSON.toJSONString(yxReturnGoodsRequest);
                HttpClientUtil.doPostJson(supplyApiConfig.getUrl() + "/returnGoods/updateReturnGoods", json2, supplyApiConfig.getHeadsMap());
            }
        }
    }

    public String getCloseRemarks(ReturnGoods returnGoodsInfo) {
        String closeRemarks = "";
        if (returnGoodsInfo.getAfterType() == 1) {
            closeRemarks = "订单已申请退款";
        } else if (returnGoodsInfo.getAfterType() == 2) {
            closeRemarks = "订单已申请退货退款";
        } else if (returnGoodsInfo.getAfterType() == 3) {
            closeRemarks = "订单已申请仅退款";
        }
        return closeRemarks;
    }

    public void updateOrderInfo(JSONObject json){
        log.info("米花科技解密后json:",json.toJSONString());
        String status = json.getString("orderStatus");
        String orderNo = json.getString("orderId");;

        OrdersPay pay = ordersDao.queryOrdersPayByResOrderNo(orderNo);
        pay.setResText(json.toJSONString());
        if (status.equals("SUCCESS")){
            String serialNumber = json.getString("mbOrderId");
            String orderAmount = json.getString("amount");

            if (StringUtils.isNotBlank(orderNo)){
                if (null == pay || (pay.getPayType().byteValue() == PayPayTypeEnums.SUCCEED.getType())) {
                    return;
                }
                // 更新支付订单信息
                if (orderAmount!=null) {
                    pay.setTotalFee( (new BigDecimal(orderAmount).multiply(new BigDecimal(100))).intValue());
                } else {
                    if (null != pay.getAmount()) {
                        BigDecimal big_total_fee = pay.getAmount().multiply(new BigDecimal(100));
                        pay.setTotalFee(big_total_fee.intValue());
                    }
                }
                pay.setPayTime(DateTimeUtil.getTime());
                pay.setPayType(PayPayTypeEnums.SUCCEED.getType());
                pay.setUpdateTime(new Date());
                pay.setTransactionId(serialNumber);
                ordersPayMapper.updateByPrimaryKeyWithBLOBs(pay);

                // 更新订单信息
                Orders orders = new Orders();
                orders.setPayType(OrderPayTypeEnums.online_pay.name());

                orders.setPaySource(OrderPaySource.alipay.name());

                orders.setIsPay(IsPayConstant.YES);
                orders.setOrderStatus(OrderStatusEnums.UNSHIPPED.getValue());
                orders.setPayTime(new Date());
                orders.setTradeNo(pay.getResOrderNo());
                orders.setAccount("米花科技");
                OrdersExample example = new OrdersExample();
                example.createCriteria()
                        .andOrderNoEqualTo(pay.getOrderNo());
                ordersMapper.updateByExampleSelective(orders, example);
                // 获取订单信息
                Orders order = ordersDao.queryOrdersByOrderNo(pay.getOrderNo());

                // 获取订单明细
                OrdersInfoExample ordersInfoExample = new OrdersInfoExample();
                ordersInfoExample.createCriteria().andOrderIdEqualTo(order.getId());
                List<OrdersInfo> ordersInfoList = ordersInfoMapper.selectByExample(ordersInfoExample);
                ordersInfoList.stream()
                        .forEach(item -> {
                            String tokenUser = redisService.get(order.getH5Token());

                            // 修改订单详情状态
                            OrdersInfo ordersInfo = new OrdersInfo();
                            ordersInfo.setId(item.getId());
                            ordersInfo.setOrderinfoStatus(OrderStatusEnums.UNSHIPPED.getValue());
                            ordersInfoMapper.updateByPrimaryKeySelective(ordersInfo);
                            try {
                                // 商品 减库存 加销量 店家加销量
                                productService.sellAfter(item.getProductId(), item.getProductSpecId(), item.getProductSum(), item.getProductPrice(),
                                        item.getIsWalletPay(),tokenUser, item.getIsDirectbuy(), item.getActivityType(), item.getActivityMax(), order.getUserId());
                            } catch (Exception e) {
                                log.error(GlobalExceptionHandler.getExceptionToString(e));
                                log.error("减库存发生异常 订单id :{}", item.getId());
                            }

                        });
                //扣减库存
                try {
                    ordersService.subStock(order.getId());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        if (status.equals("FAILED")){
            // 更新支付订单信息
            pay.setPayType(PayPayTypeEnums.FAIL.getType());
            pay.setUpdateTime(new Date());
            ordersPayMapper.updateByPrimaryKeyWithBLOBs(pay);
        }
    }

    @Override
    public Map<String, String> doUnifiedRechargeOrder(WxPayDto wxPayDto) throws Exception {
        return null;
    }

    @Override
    public Map<String, String> wxOrderQuery(String resOrderNo) throws Exception {
        return null;
    }

    @Override
    public Map<String, String> wxPhoneChargesQuery(String resOrderNo) throws Exception {
        return null;
    }

    @Override
    public Map refundOrders(String outTradeNo, String outRefundNo, Integer totalFee, Integer refundFee, String refundDesc) throws Exception {
        return null;
    }

    @Override
    public Map refundRecharge(String outTradeNo, String outRefundNo, Integer totalFee, Integer refundFee, String refundDesc) throws Exception {
        return null;
    }

    public String mhkjRefund(String mchOrderNo,String refundNo,String amount,String payTime){
        try {
            JSONObject json = new JSONObject();
            json.put("merAccount", merAccount);
            json.put("merNo", merNo);
            json.put("orderId", mchOrderNo);
            json.put("time", System.currentTimeMillis()/1000);
            json.put("merchantRefundNo", refundNo);
            json.put("refundAmt",amount);
//            json.put("mbOrderId", mbOrderId);
            json.put("refundCause", "退款");
            json.put("notifyUrl", mhkjReturnUrlNotifyUrl);


            String sign = PayUtils.buildSign(json,merKey);
            json.put("sign", sign);
            System.out.println("sign:");
            System.out.println(json.toJSONString());
            String data = PayUtils.buildDataPrivate(json,merKey);
            System.out.println(data);
            Map<String, Object> mp = new HashMap<>();
            mp.put("data", data);
            mp.put("merAccount", merAccount);
            JSONObject result = PayUtils.httpPost("https://platform.mhxxkj.com/paygateway/mbrefund/orderRefund/v1", merAccount, data);
            log.info("mhkjRefund:{}",result.toString());
            if (result!=null){
                if ("000000".equals(result.getString("code"))){
                    return "成功";
                }else{
                    return result.getString("msg");
                }
            }else{
                return "退款失败,请联系管理员";
            }
        } catch (Exception e) {
            log.error("退款报错,{}",e);
            return e.getMessage();
        }
    }


    public String mhkjRefundCj(String mchOrderNo,String refundNo,String amount,String payTime){
        try {
            JSONObject json = new JSONObject();
            json.put("merAccount", merAccount);
            json.put("merNo", merNo);
            json.put("orderId", mchOrderNo);
            json.put("time", System.currentTimeMillis()/1000);
            json.put("merchantRefundNo", refundNo);
            json.put("refundAmt",amount);
//            json.put("mbOrderId", mbOrderId);
            json.put("refundCause", "退款");


            String sign = PayUtils.buildSign(json,merKey);
            json.put("sign", sign);
            System.out.println("sign:");
            System.out.println(json.toJSONString());
            String data = PayUtils.buildDataPrivate(json,merKey);
            System.out.println(data);
            Map<String, Object> mp = new HashMap<>();
            mp.put("data", data);
            mp.put("merAccount", merAccount);
            JSONObject result = PayUtils.httpPost("https://platform.mhxxkj.com/paygateway/mbrefund/orderRefund/v1", merAccount, data);
            log.info("mhkjRefund:{}",result.toString());
            if (result!=null){
                if ("000000".equals(result.getString("code"))){
                    return "成功";
                }else{
                    return result.getString("msg");
                }
            }else{
                return "退差价失败,请联系管理员";
            }
        } catch (Exception e) {
            log.error("退差价报错,{}",e);
            return e.getMessage();
        }
    }

}
